package Tester;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import javax.swing.JPanel;


public class Controls extends JPanel implements KeyListener{

	/**
	 * 
	 */

	private static final long serialVersionUID = 1L;

	public Controls(int size) {
		this.size = size;
		//Generate vector with specified size and fill it.
		int[] vector = new int[(int) Math.pow(size, 2)]; //Create vector with the specified size
		for(int i = 1; i <= Math.pow(size, 2); i++)
			vector[i-1] = i;//Fill vector with sorted values
		result = new int[size][size];
		int k = 0;
		for (int i = 0; i < size; i++) {
			for (int j = 0; j < size; j++) {
				result[i][j] = vector[k];
				k++;
			}

		}


		shuffle(vector);//Shuffle vector
		matrix = matrix(vector);//Copy values of shuffled vector into matrix

		//find size^2 in the matrix (blank tile) to start the listener. 
		for(int i = 0; i < this.matrix.length; i++)
		{
			for(int j = 0; j < this.matrix.length; j++)
			{
				if(this.matrix[i][j] == (int)(Math.pow(this.matrix.length, 2)))
				{
					indexi = i;
					indexj = j;
				}
			}
		}

		Rectangle[][] rectangles = new Rectangle[size][size];
		for (int i = 0; i < size; i++) {
			for (int j = 0; j < size; j++) {
				rectangles[i][j] = new Rectangle( i*(sizex/size),j*(sizey/size), ((sizex/size)), ((sizey/size)));
				//Simple math for alignment and size
			}
		}

		this.rectangles = rectangles;	

		addKeyListener(this);
		setFocusable(false);
		repaint();
	}

	/**
	 * Fisher Yates Shuffle
	 * @param vector with shuffled values
	 */
	private void shuffle(int[] vector) {
		Random random = new Random();
		for (int i = 0; i < vector.length; i++) {
			int j = i + random.nextInt(vector.length - i); //Random number from 0 <= j <= i
			//swap values;
			int temp = vector[i];
			vector[i] = vector[j];
			vector[j] = temp;	
		}
	}

	/**
	 * Copy shuffled vector into matrix
	 * @param vector 
	 * @return Matrix with shuffled values
	 */
	private int[][] matrix(int[] vector){
		int k = 0;
		int[][] matrix = new int[size][size];
		for(int i = 0; i < size; i++){
			for(int j = 0; j < size; j++){
				matrix[i][j] = vector[k];
				k++;
			}
		}
		return matrix;
	}

	/**
	 * Controls work pretty simple, action listener triggers > keylistener. When it's
	 * triggered it verifies if any of the specified keys were used.
	 * The swapping occures simulating that indexi = y and indexj = x; 
	 * 
	 * The logic is swap the n^2 with the desired tile and then store the location of n^2 in memory again.
	 */
	public void left() {	
		try {
			int temp = matrix[indexi][indexj];
			matrix[indexi][indexj] = matrix[indexi][indexj - 1];
			matrix[indexi][indexj - 1] = temp;
			indexj -= 1;
			repaint();
			verify();
		} catch (Exception e) {
			e.printStackTrace();
		}


	}
	public void right() {	
		try {
			int temp = matrix[indexi][indexj];
			matrix[indexi][indexj] = matrix[indexi][indexj + 1];
			matrix[indexi][indexj + 1] = temp;
			indexj += 1;
			repaint();
			verify();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	public void up() {	
		try {
			int temp = matrix[indexi][indexj];
			matrix[indexi][indexj] = matrix[indexi - 1][indexj];
			matrix[indexi - 1][indexj] = temp;
			indexi -= 1;
			repaint();
			verify();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("Test");
	}
	public void down() {	
		try {
			int temp = matrix[indexi][indexj];
			matrix[indexi][indexj] = matrix[indexi + 1][indexj];
			matrix[indexi + 1][indexj] = temp;
			indexi += 1;
			repaint();
			verify();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	public void keyPressed(KeyEvent e) {

		if(e.getKeyCode() == KeyEvent.VK_UP);
		up();
		if(e.getKeyCode() == KeyEvent.VK_DOWN);
		down();
		if(e.getKeyCode() == KeyEvent.VK_LEFT);
		left();
		if(e.getKeyCode() == KeyEvent.VK_RIGHT);
		right();

	}



	public void paintComponent(Graphics g)
	{
		Graphics2D g2 = (Graphics2D) g;
		super.paintComponents(g2);
		draw(g2);

	}

	public int[][] getMatrix() {
		return matrix;
	}

	public void draw(Graphics2D g2) {

		for(int i = 0; i < matrix.length; i++)
		{
			for(int j = 0; j < matrix.length; j++)
			{
				boolean paint = true;
				if(matrix[j][i] == (int)Math.pow(matrix.length, 2))
					paint = false;
				if(paint){
					g2.setColor(Color.BLACK);
					g2.draw(rectangles[i][j]);	
					g2.setColor(Color.WHITE);
					g2.fill(rectangles[i][j]);

					if(matrix[j][i] % 2 == 0)
						g2.setColor(Color.BLUE);
					else
						g2.setColor(Color.RED);

					g2.drawString(Integer.toString(matrix[j][i]),(int)rectangles[i][j].getCenterX(), (int)rectangles[i][j].getCenterY());

				}
				else {
					g2.setColor(Color.DARK_GRAY);
					g2.draw(rectangles[i][j]);
					g2.fill(rectangles[i][j]);
				}
			}
		}
	}


	public void verify(){
		boolean sorted = true;
		for (int i = 0; i < size; i++) {
			for (int j = 0; j < size; j++) {
				if(result[i][j] != matrix[i][j])
					sorted = false;
			}

		}
		if(sorted)
		{
			System.out.println("Winner winner chicken dinner!");
			System.exit(0);
		}
	}



	public void keyReleased(KeyEvent e){}
	public void keyTyped(KeyEvent e){}

	private int[][] result; 
	private int[][] matrix;	
	private int indexi;
	private int indexj;
	private int size;
	public Rectangle[][] rectangles;
	public static final int sizex = 400;
	public static final int sizey = 400;




}
